package main

import (
	"fmt"
	"gitee.com/xiakai001/goutl/animeutl"
	"gitee.com/xiakai001/goutl/cmdutl"
	"gitee.com/xiakai001/goutl/errutl"
	"gitee.com/xiakai001/goutl/goutl"
	"github.com/dengsgo/math-engine/engine"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
)

func main() {

	defer func() {
		for {
			_, _ = fmt.Scanln()
		}
	}()

	err := handle()
	if err != nil {
		println(err.Error())
	}

}

var picNameFormat = regexp.MustCompile("extracted_\\d+.png")

func handle() error {
	if len(os.Args) <= 1 {
		println("无文件路径")
		return nil
	}

	config, err := goutl.LoadJsonFromFile[*Config](filepath.Join(filepath.Dir(os.Args[0]), "config.json"))
	if err != nil {
		return errutl.Wrap(err)
	}

	args := make([]string, 0, len(os.Args))
	for _, arg := range os.Args[1:] {
		args = append(args, arg)
	}

	goutl.SortAsc(args)

	for _, path := range args {
		dirPath := strings.TrimSuffix(path, filepath.Ext(path))
		_, err := os.ReadDir(dirPath)
		if err != nil {
			return errutl.Wrap(err)
		}
	}

	for _, path := range args {
		err := handleVideo(config, path)
		if err != nil {
			return errutl.Wrap(err)
		}
	}

	println()
	println()
	println("success!!")
	println()
	println()

	return nil
}

func handleVideo(config *Config, filePath string) error {

	if config == nil || len(config.Crf) == 0 || len(config.Preset) == 0 {
		return errutl.New("config is nil")
	}

	fmt.Printf("start mv: %s\n", filepath.Base(filePath))

	// 获取图片路径
	dirPath := strings.TrimSuffix(filePath, filepath.Ext(filePath))
	picDir, err := os.ReadDir(dirPath)
	if err != nil {
		return errutl.Wrap(err)
	}

	// 获取图片数
	picCount := 0
	for _, entry := range picDir {
		if picNameFormat.MatchString(entry.Name()) {
			picCount++
		}
	}
	fmt.Printf("图片数: %d\n", picCount)

	// 获取原始视频的编码等信息
	probeResult, err := animeutl.GetProbe(filePath)
	if err != nil {
		return errutl.Wrap(err)
	}

	// 获取视频时长
	duration, err := probeResult.GetVideoDuration()
	if err != nil {
		return errutl.Wrap(err)
	}
	fmt.Printf("视频时长: %.9f\n", duration)

	if duration <= 0 {
		return errutl.New("duration <= 0")
	}

	baseName := filepath.Base(dirPath)
	// 计算帧率
	var frameRateStr string
	if strings.HasPrefix(baseName, "cut_") {
		frameRateStr = probeResult.GetVideoFrameRate()
		fmt.Printf("cut-frameRate: %s\n", frameRateStr)
	} else {
		vFrameRate, err := engine.ParseAndExec(probeResult.GetVideoFrameRate())
		if err != nil {
			return errutl.Wrap(err)
		}
		picFrameRate := float64(picCount) / duration
		if goutl.Abs(vFrameRate-picFrameRate) > 0.01 {
			return errutl.New("vFrameRate != picFrameRate")
		}
		frameRateStr = strconv.FormatFloat(picFrameRate, 'f', -1, 64)
		fmt.Printf("pic-frameRate: %s\n", frameRateStr)
	}
	if len(frameRateStr) == 0 {
		return errutl.New("frameRate is 0")
	}

	outputFilePath := filepath.Join(config.Output, "1_"+baseName+".mp4")
	// 使用os.Stat来获取文件信息
	exist, err := goutl.FileExist(outputFilePath)
	if err != nil {
		return errutl.Wrap(err)
	}
	if exist {
		return errutl.New("输出文件已存在")
	}

	args := []string{"-r", frameRateStr,
		"-hwaccel", "auto", "-y", "-f", "image2",
		"-i", fmt.Sprintf("%s\\extracted_%%d.png", dirPath),
		"-vcodec", "libx265", "-pix_fmt", "yuv420p10le",
		"-crf", config.Crf, "-vf", "pad=ceil(iw/2)*2:ceil(ih/2)*2",
		"-preset", config.Preset, "-tune", "animation",
		outputFilePath}
	println("ffmpeg", strings.Join(args, " "))
	//ffmpeg -r 8297/346 -hwaccel auto -y -f image2 -i E:\101\extracted_%d.png -vcodec libx265 -pix_fmt yuv420p10le -crf 10 -vf pad=ceil(iw/2)*2:ceil(ih/2)*2 -preset slower -tune animation G:\文件\MV\1-101.mkv

	err = cmdutl.ExecWithArgs("ffmpeg", args)
	if err != nil {
		return errutl.Wrap(err)
	}

	return nil
}
